<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * new的封装
    *   new方法是一个操作符，不能够添加到原型当中
    *   new Foo(x,y) 原始系统自带写法
    *       new方法返回一个对象：这个对象关联到Foo的this中，对象的原型在Foo.prototype中
    *
    *   myNew(Foo,x,y) 我们封装的写法
    *
    * */

    function myNew(Foo,...arg){

        //因为new方法最后返回一个对象，所以先创建一个对象
        let result = {}

        //这一步对result对象的原型进行修改，有原来的Object.prototype指向实例出该result对象的构造函数Foo的原型Foo.prototype
        result.__proto__ = Foo.prototype

        //函数Foo执行，Foo执行的时候，需要以result对象的this指向作为主体来执行，就是Foo的this指向result
        Foo.apply(result,arg) //可以使用call，但是call需要用点点点结构赋值，而apply接收的参数是数组形式不用结构更方便

        //最后返回result对象
        return result
    }

    let Foo = function (a){ //接收一个形参a
        this.a = a //函数Foo实例出来的对象，内部创建一个a属性，属性a的值为接收的形参a的值
    }
    Foo.prototype.say =function (){ //函数Foo的原型上添加一个say方法
        console.log(this.a)
    }

    let  obj = myNew(Foo,1)

    console.log(obj)
    console.log(obj.say) //obj.say来自于谁的prototype？obj是myNew方法return出来的result对象，因为是对象，所以obj最初的原型来自于Object.prototype
    //但是因为obj是通过new方法由构造函数Foo实例出来的对象，而构造函数Foo实例出来的对象应该带有Foo的原型prototype，所以使用new方法实例出来的对象obj的原型，
    //就应该从原来的Object的原型Object.proto 转变为 Foo的原型Foo.prototype，构造函数Foo的原型上有say方法，所以实例对象obj也应有say方法


</script>
</body>
</html>